home *** CD-ROM | disk | FTP | other *** search
/ BBS Toolkit / BBS Toolkit.iso / doors_1 / doorskl3.zip / DOORSKEL.C < prev    next >
C/C++ Source or Header  |  1991-12-15  |  28KB  |  1,005 lines

  1. /**********************************************/
  2. /*                                              */
  3. /* XBBS Door Skeleton -- TC 2.0/MSC 6.0a code */
  4. /* Copyright (c) 1990/91 by M. Kimes          */
  5. /* All Rights Reserved                        */
  6. /* May be freely used for >>>FREE<<< programs */
  7. /* as long as you don't try to save any souls */
  8. /* (nasty habit)                              */
  9. /*                                            */
  10. /**********************************************/
  11.  
  12. /* Always include this module (with appropriate #defines) */
  13.  
  14. /**************************************************************************
  15.   Miscellaneous notes:
  16.  
  17.     #define XBBS and the program will be compiled to read ONLINE.XBS
  18.     #define DORINFO and the program will be compiled to read DORINFO?.DEF
  19.     #define both and first ONLINE.XBS will be read, then DORINFO?.DEF
  20.     (don't know why you'd wanna do that)
  21.     #define neither and all info must come from command line
  22.     #define FINDUSER and a routine to find a given user (by name) will
  23.             be compiled in (finduser()) for XBBS' USERS.BBS
  24.     #define NOREADFILE and the file reader routine (readtext()) will NOT
  25.             be compiled
  26.     #define DISABLEBREAK to disable CTRL-BREAK/CTRL-C
  27.     #define DIALTRANS to include a dial_trans function for modem dialing,
  28.             etc.
  29.  
  30.     set chars to be unsigned by default
  31.     recommend large model (recompile screen2.asm and ansi.asm if other)
  32.     this code requires a FOSSIL for serial i/o--see function fossil()
  33.  
  34.     My indenting style is thanks to Mike Looney who taught me everything
  35.     he knows.  ;^D
  36. ***************************************************************************/
  37.  
  38. #include "doorskel.h"   /* DOORSKEL's include file */
  39.  
  40.  
  41. /* Conditional global variables created here */
  42.  
  43. #ifdef XBBS
  44.     struct _config conf;
  45.     struct _user   user;
  46.     word           userno;
  47.     struct time    timeon;
  48.     char           timer_off;
  49.     word           hold_time;
  50.     char           age;
  51.     char           pages;
  52.     struct _mboard mboard;
  53.     struct _fboard fboard;
  54.     struct _events event[10];
  55.     char           variable[10][82];
  56.     ulong           starter;
  57. #endif
  58.  
  59.  
  60. /* Global variables created here -- NOTE DEFAULTS! */
  61.  
  62. char   debug_mode       = 0;
  63. char   graphics         = 0;
  64. time_t timelimit;
  65. word   baud             = 0;
  66. char   numlines         = 24;
  67. word   seclvl           = 5;
  68. time_t startt           = 0;
  69. char   sysopin          = 0;
  70. char   fastANSI         = 1;
  71. char   commport         = 0;
  72. char   logfile[133]     = "XBBS.LOG";
  73. char   username[36]     = "A. Ghost";
  74. char   width            = 80;
  75. char   chatting         = 0;
  76. char   chatted          = 0;
  77. char   nodenumber       = 1;
  78. char   system_name[64]  = "";
  79. char   sysop[36]        = "";
  80.  
  81. /* These are tied to the screen2.asm module */
  82.  
  83. int    maxx,maxy;           /* size of local screen */
  84. word   videomethod,vbase;
  85. char   current_color = 7,cls_clr = 7;
  86.  
  87. int FAR *vseg;      /* this one we use for internal dputs() replacement */
  88.  
  89. #ifdef __TURBOC__
  90.     extern unsigned _Cdecl _stklen = 8192; /* Stack length; adjust if req'd */
  91.                                            /* note MSC adjusts stack at compile or link time */
  92. #endif
  93.  
  94.  
  95.  
  96.  
  97.  
  98. void _cdecl main (int argc,char **argv) {
  99.  
  100.     register int x;
  101.     char         *p;
  102.  
  103.  
  104.   set_mtask();  /* see mtask.c */
  105.  
  106.   /* Please leave this next line in as a courtesy...thanks */
  107.   fputs(
  108.       "\x1b[2J\x1b[0;2;37m\x1b[1;1H\r\04 Built from M. Kimes' DOORSKEL kit v1.03.\n",
  109.       stdout);
  110.  
  111.   srand((unsigned)time(NULL));
  112.   videomethod = 0;                      /* default direct video */
  113.   vbase = (vmode() == 7 ? 0xb000: 0xb800);  /* find base address of video ram */
  114.   vseg = MK_FP(vbase,0);                /* address of video ram as pointer */
  115.   timelimit = time(NULL) + (30L * 60L); /* default 30 min timelimit */
  116.   set_screen_size();                    /* find screen size */
  117.   setcoords(0,0,maxx - 1,maxy - 2);     /* change if you want more than one */
  118.                                         /* status line or whatever */
  119.  
  120. #ifdef DISABLEBREAK
  121.   signal(SIG_INT,break_handler);
  122. #endif
  123.  
  124.   /* check for help request */
  125.   if (argc == 2 && (!strcmp(argv[1],"?" || !stricmp(argv[1],"H"))) {     
  126.     printinfo();   /* FILENAME H or FILENAME ? on command line */
  127.     printhelp();
  128.     exit(0);
  129.   }
  130.  
  131.   set_raw();                                    /* for output speed */
  132.  
  133.   atexit(deinitialize);
  134.  
  135.   /* read exit files per conditional compilation */
  136.  
  137. #ifdef XBBS
  138.     readconfig();
  139.     getonline();
  140. #endif
  141.  
  142. #ifdef DORINFO
  143.     readinfo();
  144. #endif
  145.  
  146.   for (x = 1;x < argc;x++) {    /* process command line args */
  147.  
  148. ReSwitch:
  149.  
  150.     switch (toupper(*argv[x])) {
  151.         case '-':   /* ignore common "switch" chars */
  152.         case '/':   memmove(argv[x],&argv[x][1],strlen(argv[x]));
  153.                     goto ReSwitch;
  154.  
  155.         case 'F':   fastANSI = 0;   /* turn INT 29H fastwriting off */
  156.                     break;
  157.  
  158.         case 'U':   strncpy(username,&argv[x][1],36);   /* user's name */
  159.                     username[35] = 0;
  160.                     break;
  161.  
  162.         case 'N':   nodenumber = (char)atoi(&argv[x][1]);   /* node number */
  163.                     break;
  164.  
  165.         case 'L':   numlines = (char)atoi(&argv[x][1]); /* length of user's screen */
  166.                     break;
  167.  
  168.         case 'W':   width = (char)atoi(&argv[x][1]);    /* width of user's screen */
  169.                     break;
  170.  
  171.         case 'B':   baud = (word)atoi(&argv[x][1]);     /* current baud rate */
  172.                     break;                              /* 0 = local only    */
  173.  
  174.         case 'G':   if(atoi(&argv[x][1])) graphics = 1; /* ANSI on if non-zero */
  175.                     break;
  176.  
  177.         case 'C':   commport = (char)atoi(&argv[x][1]); /* 0 = COM1 */
  178.                     break;
  179.  
  180.         case 'S':   seclvl = atoi(&argv[x][1]);         /* security level */
  181.                     break;
  182.  
  183.         case 'T':   timelimit = time(NULL) + ((atol(&argv[x][1])) * 60L); /* time in minutes */
  184.                     break;
  185.  
  186.         case 'M':   videomethod = atoi(&argv[x][1]);  /* for direct screen write control; 0 = direct, 1 = bios */
  187.                     break;
  188.  
  189.         case '!':   debug_mode = 1;                   /* turn on debug printing */
  190.                     break;
  191.  
  192.         case 'X':   strcpy(logfile,&argv[x][1]);      /* set logfile */
  193.                     break;
  194.  
  195.         /********* add any special command switches here **********/
  196.         /********* remember to add help in printhelp() below ******/
  197.  
  198.         default:    fputs("\nUnknown argument `",stdout);
  199.                     fputs(argv[x],stdout);
  200.                     fputs("'\n",stdout);
  201.                     my_sleep(1);
  202.     }
  203.   }
  204.   setfastansi(fastANSI);
  205.   fossil(INIT,0);   /* activates FOSSIL driver */
  206.   cls();            /* clear our screen and theirs */
  207.  
  208.   printg("\x1b[0;1;37m");   /* default colors for ANSI users */
  209.   p = PROGRAM_NAME;         /* transmit program name */
  210.   if(baud) while (*p++) while(!fossil(TRANSMIT,*p)) carrchk();
  211.   printinfo();              /* print local program id info */
  212.   printm("\r\n");
  213.  
  214.   mainloop();       /* jumps to your "program" in DOORSKL4.C */
  215.  
  216. /*  If you want to change parameters in CONFIG.BBS or ONLINE.XBS,
  217.  *  change them, then call saveconfig() or prepare() here or in
  218.  *  deinitialize() (only for XBBS use)
  219.  */
  220.  
  221. }
  222.  
  223.  
  224.  
  225. void _fastcall printhelp (void) {  /* Print help screen--edit to taste
  226.                                       Add to as required */
  227.  
  228.     fputs(" Command line arguments:\n"
  229.           "L<screen lines>\n"
  230.           "N<nodenumber>\n"
  231.           "U<user name>\n"
  232.           "W<screen width>\n"
  233.           "T<time in minutes>\n"
  234.           "B<baudrate (0-38400...?)>\n"
  235.           "G<graphics (0 or 1)>\n"
  236.           "C<commport (0=COM1)>\n"
  237.           "S<security level>\n"
  238.           "M<mode (0=direct video, 1=BIOS, 2=DOS)>\n"
  239.           "X<filename> (Log File)\n"
  240.           "F (Fast ANSI writes (through INT 29H) off)\n"
  241.           "! (Debug mode on)\n",stdout);
  242.  
  243. #ifdef DORINFO
  244.     fputs(" Requires a DORINFO?.DEF file\n",stdout);
  245. #endif
  246.  
  247. #ifdef XBBS
  248.     fputs(" Requires XBBS ONLINE.XBS and CONFIG.BBS files\n",stdout);
  249. #endif
  250. }
  251.  
  252.  
  253.  
  254.  
  255. #ifdef DISABLEBREAK
  256.  
  257. void _cdecl break_handler (int sigl) {      /* guess */
  258.  
  259.   signal(SIGINT,SIG_IGN);
  260.   /* do whatever you want; don't use printf for msgs, use dprintf */
  261.   signal(SIGINT,break_handler);
  262.   return;
  263. }
  264.  
  265. #endif
  266.  
  267.  
  268.  
  269. void _fastcall chat (void) {   /* Cheap chat-mode */
  270.  
  271.     char a[3];
  272. #ifndef __TURBOC__
  273.     union REGS r;
  274. #endif
  275.  
  276.  
  277.     printg("\x1b[0;1;33m");
  278.     printm("\r\n\r\nChat mode engaged\r\n\r\n");
  279.     while (chatting) {
  280.        *a = inkey();
  281.        a[1] = 0;
  282.        if (chatting) {
  283. #ifdef __TURBOC__
  284.          _AH = 3;
  285.          _BH = 0;
  286.          geninterrupt(16);
  287. #else
  288.          r.h.ah = 3;
  289.          r.h.bh = 0;
  290.          int86(16,&r,&r);
  291. #endif
  292.          if (*a == '\r') printm("\r\n");
  293. #ifdef __TURBOC__
  294.          if ((*a == '\r') || (*a == ' ' && _DL > maxx - 10)) printm("\r\n");
  295. #else
  296.          if((*a == '\r') || (*a == ' ' && r.h.dl > maxx - 10)) printm("\r\n");
  297. #endif
  298.          else printm(a);
  299.        }
  300.     }
  301.     printm("\r\n\r\nChat mode ended\r\n\r\n");
  302.     chatted++;
  303. }
  304.  
  305.  
  306.  
  307.  
  308. char _fastcall inkey (void) {       /* like BASIC's INKEY$ local and remote */
  309.  
  310.     char arg = 0;
  311.     union REGS rg;
  312.  
  313.  
  314.     rg.h.ah = 11;
  315.     int86(0x21,&rg,&rg);    /* check DOS for key waiting */
  316.     if (rg.h.al) {          /* key is waiting */
  317.         rg.h.ah = 8;
  318.         int86(0x21,&rg,&rg);
  319.         if (rg.h.al) return((char)(rg.h.al));   /* got normal key */
  320.         rg.h.ah = 8;                            /* else got extended key */
  321.         int86(0x21,&rg,&rg);
  322.         arg = specialkey(rg.h.al);
  323.         if (arg) return (arg);      /* is a non-reserved extended key */
  324.     }
  325.  
  326.     if (baud) {
  327.       arg = carrchk();  /* check carrier and whether a key is available */
  328.       if (!(arg & 1)) return 0; /* no key available */
  329.       fossil(RECVWAIT,arg);
  330.       if(!arg || arg == '\x1b') return specialmod(arg); /* ANSI or Doorway key else normal key */
  331.       return arg;
  332.     }
  333.  
  334.     getxbbstime();  /* check timeleft, update status line */
  335.  
  336.     pause_mtask();  /* give up timeslice */
  337.     return 0;       /* return "no key" */
  338. }
  339.  
  340.  
  341.  
  342. char _fastcall specialmod (char wuz) {
  343.  
  344.     /* process "extended" keys and ANSI cursor keys */
  345.  
  346.     char arg;
  347.     clock_t t1;
  348.  
  349.  
  350.       t1 = timerset(250L);
  351.       while(!timeup(t1)) {
  352.           arg = carrchk();
  353.           if (arg & 1) break;       /* 1/4 sec for next part of key sequence */
  354.       }
  355.  
  356.       if (!(arg & 1)) return 0;
  357.       arg = (fossil(RECVWAIT,arg));
  358.       if(!wuz) return (arg | 128);  /* "Doorway" key */
  359.       if (arg != '[') return 0;     /* it's a bad ANSI sequence */
  360.  
  361.       t1 = timerset(250L);          /* we have <-[ so far... */
  362.       while(!timeup(t1)) {
  363.           arg = carrchk();
  364.           if(arg & 1) break;
  365.       }
  366.  
  367.       arg = carrchk();
  368.       if(!(arg & 1)) return 0;
  369.       arg = (fossil(RECVWAIT,arg));
  370.       if((arg != '1') && (arg != 'A') && (arg != 'B') &&
  371.           (arg != 'C') && (arg != 'D') && (arg != 'K'))
  372.           return 0;   /* not an ANSI sequence we recognize */
  373.  
  374.       /* note internal representation of cursor keys */
  375.  
  376.       if(arg == 'A') return UP;
  377.       if(arg == 'B') return DN;
  378.       if(arg == 'C') return RIGHT;
  379.       if(arg == 'D') return LEFT;
  380.       if(arg == 'K') return DEL;
  381.  
  382.       /* some terms send <-[1A, some just send <-[A; this checks former */
  383.  
  384.       t1 = timerset(250L);
  385.       while(!timeup(t1)) {
  386.           arg = carrchk();
  387.           if (arg & 1) break;
  388.       }
  389.  
  390.       arg = carrchk();
  391.       if(!(arg & 1)) return 0;
  392.       arg = (fossil(RECVWAIT,arg));
  393.       if((arg != 'A') && (arg != 'B') && (arg != 'C') &&
  394.          (arg != 'D')) return 0;
  395.       if(arg == 'A') return UP;
  396.       if(arg == 'B') return DN;
  397.       if(arg == 'C') return RIGHT;
  398.       if(arg == 'D') return LEFTT;
  399.  
  400.       return 0;
  401. }
  402.  
  403.  
  404.  
  405.  
  406. char _fastcall specialkey (char a) {
  407.  
  408.    /* this function processes extended local keys.  add your own... */
  409.    /* a is second half of scan code (0 + a) */
  410.  
  411.   switch (a) {
  412.  
  413.     case 45:cls();          /* ALT-Q for example, 0 + 45 */
  414.             exit(0);        /* QUIT DOOR */
  415.  
  416.     case 35:                /* HANG UP */
  417.             fossil(DTR,DOWN);
  418.             exit(1);
  419.  
  420.     case 46:                /* chat mode */
  421.             chatting = 1 - chatting;
  422.             if(chatting) chat();
  423.             return 0;
  424.  
  425.     case 36:                /* SysOp SHELL */
  426.             cls();
  427.             printm(" \x1b[0m\r\nThe SysOp has jumped to DOS...please wait...\r\n");
  428.             fossil(FLUSHOUT,0);
  429.             pause_mtask();
  430.             spawnit(getenv("COMSPEC"));
  431.             printm("\r\nThe SysOp has returned...please continue...\r\n");
  432.             my_sleep(1);
  433.             return(0);
  434.  
  435.     case 131:             /* MORE TIME... ALT + */
  436.             timelimit += 60L;
  437.             return 0;
  438.  
  439.     case 130:             /* LESS TIME... ALT - */
  440.             if (timelimit - getxbbstime() < 60L) timelimit = time(NULL);
  441.             else timelimit -= 60L;
  442.             return 0;
  443.  
  444.   }
  445.  
  446.   return (a | 128);       /* return "extended key" */
  447. }
  448.  
  449.  
  450.  
  451.  
  452. void _fastcall cls (void) {             /* like BASIC's CLS */
  453.  
  454.     char *clr_string = "\x1b[0m\x1b[2J";
  455.  
  456.  
  457.     /* first clear remote */
  458.  
  459.     if(!graphics) clr_string = "\xc";
  460.     if(baud) {
  461.         while (*clr_string++) {
  462.             while(!fossil(TRANSMIT,*clr_string)) carrchk();
  463.         }
  464.     }
  465.  
  466.     /* then clear local */
  467.  
  468.     fputs("\x1b[0m\x1b[2J",stdout);
  469.     print_stat();   /* replace erased status line */
  470. }
  471.  
  472.  
  473.  
  474. char _fastcall fossil (char function,char arg) {
  475.  
  476.     /* handles most common fossil calls */
  477.     /* see FOSSIL.DOC or FSC-0015 for more info on FOSSIL drivers */
  478.  
  479.     union REGS rg;
  480.  
  481.  
  482.     if(!baud) return 0;
  483.     if (function == FLUSHOUT) {
  484.        do {
  485.            carrchk();
  486.            rg.h.ah = 3;
  487.            rg.x.dx = commport;
  488.            int86(20,&rg,&rg);
  489.        } while (!(rg.h.ah & 64));
  490.        return(0);
  491.     }
  492.  
  493.     if (function == WATCHDOG) rg.h.al = arg;
  494.     else if (function == DTR) rg.h.al = arg;
  495.     else if (function == TRANSWAIT) rg.h.al = arg;
  496.     else if (function == TRANSMIT) rg.h.al = arg;
  497.     else if (function == ONOFF) rg.h.al = arg;
  498.  
  499.     rg.x.dx = commport;
  500.     rg.h.ah = function;
  501.     int86(20,&rg,&rg);
  502.  
  503.     if (function == INIT) {
  504.        if (rg.x.ax != INITOK) { /* ARGH!  couldn't initialize FOSSIL */
  505.            fputs("\nFossil not responding...RTFM.\n",stdout);
  506.            exit (3);
  507.        }
  508.        return (0);
  509.     }
  510.  
  511.     if (function == GETSTAT) {
  512.        arg = rg.h.ah;
  513.        if (rg.h.al & 128) {
  514.            arg |= 128;
  515.            return (arg);
  516.        }
  517.        arg &= 127;
  518.        return (arg);
  519.     }
  520.  
  521.     if (function == RECVWAIT) return rg.h.al;
  522.     if (function == TRANSMIT) return (char)rg.x.ax;
  523.  
  524.     return (0);
  525. }
  526.  
  527.  
  528.  
  529. void _cdecl deinitialize (void) {    /* deinit fossil, etc. at exit */
  530.  
  531.     fossil(FLUSHOUT,0);
  532.     fossil (DEINIT,0);
  533.  
  534.     fcloseall();
  535.  
  536.     set_cooked();
  537.  
  538.     /* put other atexit stuff you need here... */
  539.  
  540.     printm("\r\n");
  541.     fputs("\x1b[0;2;37m\n",stdout);
  542. }
  543.  
  544.  
  545.  
  546. /* generic input routine -- see types in doorskel.h */
  547.  
  548. char * _fastcall genin (char length,    /* maximum length of user input */
  549.                         char password,  /* "shroud" input echo if non-zero */
  550.                         char caps,      /* force input to uppercase if non-zero */
  551.                         char hot,       /* "hot" input if non-zero */
  552.                         char type) {    /* type of input -- see doorskel.h */
  553.  
  554. static char input[257];
  555. int x = 0;
  556. char one = 0;
  557. char randchr[2];
  558.  
  559.  
  560.  length--;  /* note */
  561.  
  562. AfterChat:
  563.  
  564.  strset(input,0);
  565.  startt = getxbbstime();
  566.  
  567.  while ((getxbbstime() - startt) < 241 || (chatted != 0)) {
  568.  
  569.   one = inkey();
  570.   if (one == '\r') break;
  571.  
  572. Nogo:
  573.  
  574.   if (one == 8) {
  575.       if (x > 0) {
  576.          printm(BACKSPACE);
  577.          input [--x]=0;
  578.          if ((type == PHONE) && ((x == 2) || (x == 5))) printm(BACKSPACE);
  579.          if ((type == DATE) && ((x == 3) || (x == 5))) printm(BACKSPACE);
  580.       }
  581.       continue;
  582.   }
  583.   if (type == ARROWS) {
  584.     switch (one) {
  585.         case UP:
  586.         case DN:
  587.         case RIGHT:
  588.         case LEFT:
  589.         case 3:
  590.         case '?':
  591.         case 27:
  592.         case 11:    *input = one;
  593.                     return (input);
  594.         case 13:    *input = 0;
  595.                     return (input);
  596.     }
  597.     if (isprint(one)) {
  598.         *input = toupper(one);
  599.         return (input);
  600.     }
  601.     continue;
  602.   }
  603.  
  604.   if ((caps) || (type == YESNO) || (type == YESNOM) || (type == FLE) || (type == FLEW) || (type == FLEPW) || (type == FLEP) || (type == FLENX)) one = toupper(one);
  605.   if (x <= length) {
  606.       if(type == HYPER && (one == 27 || one == 11)) goto BreakOutOfIt;
  607.       if(type == HYPER && graphics && one < 6 && one != 3) goto BreakOutOfIt;
  608.       if (type == NAME) {
  609.         if((isalpha(one) == 0) && (one != ' ') && (one != '.') && (one != '-') || (x == 0 && one == ' ')) continue;
  610.         if ((one == ' ') && (strchr(input,' ') != NULL)) continue;
  611.       }
  612.       if (type == NEAT) {
  613.         if((isalnum(one) == 0) && (one != ' ') || (x == 0 && one == ' ')) continue;
  614.       }
  615.       if ((type == NEAT) || (type == NAME)) {
  616.         if(x == 0) {
  617.             one = toupper(one);
  618.         }
  619.         else one = tolower(one);
  620.       }
  621.       if((type == NEAT) || (type == NAME)) {
  622.         if((x > 0) && ((input[x - 1] == ' ') || (input[x - 1] == '.') || (input[x-1] == '-'))) one = toupper(one);
  623.       }
  624.       if ((type == SUBJECT) && (x == 0)) one = toupper(one);
  625.       if ((type == SUBJECT) && (isprint(one) == 0)) continue;
  626.       if ((type == ALLL) && (isprint(one) == 0)) continue;
  627.       if ((type == ALLL) && (one == 127)) one = 8;
  628.       if ((type == ALPHA) && (isalpha(one) == 0) && (one != ' ')) continue;
  629.       if (((type == NUM) || (type == PHONE) || (type == DATE)) && (isdigit(one) == 0)) continue;
  630.       if ((type == ALPHANUM) && (isalnum(one) == 0) && (one != ' ')) continue;
  631.       if (((type == YESNO) || (type == YESNOM)) && (one != 'Y' && one != 'N')) continue;
  632.       if (type == FLE) {
  633.          if ((isalnum(one) == 0) && (!strchr("._-+=!@#$%^&/",one))) continue;
  634.       }
  635.       if (type == FLENX) {
  636.          if ((isalnum(one) == 0) && (!strchr("_-+=!@#$%^&/",one))) continue;
  637.       }
  638.       if (type == FLEP) {
  639.          if ((isalnum(one) == 0) && (!strchr("._-+=!@#$%^&/\\:",one))) continue;
  640.       }
  641.       if (type == FLEW) {
  642.           if ((isalnum(one) == 0) && (!strchr("._-+=!@#$%^&/?*",one))) continue;
  643.       }
  644.       if (type == FLEPW) {
  645.         if ((isalnum(one) == 0) && (!strchr("._-+=!@#$%^&/?*\\:",one))) continue;
  646.       }
  647.       if ((type == FLE) || (type == FLEP) || (type == FLEW) || (type == FLEPW)) {
  648.          if ((one == '.') && (strchr(input,'.') != NULL)) continue;
  649.       }
  650. BreakOutOfIt:
  651. ;
  652.    }
  653.    if (chatted > 0) {   /* allow for chat having interrupted us */
  654.     chatted = 0;
  655.     goto AfterChat;
  656.    }
  657.    if ((one != 0) && (x <= length)) {
  658.       input[x] = one;
  659.       input[++x] = 0;
  660.       if (type == YESNOM) {
  661.           return(input);
  662.       }
  663.       if (password == 0) printm(&input[x - 1]);
  664.       if (password != 0) {
  665.         randchr[0] = (rand() % 10) + 33;
  666.         randchr[1] = 0;
  667.         printm(randchr);
  668.       }
  669.       if ((type == PHONE) && ((x == 3) || (x == 6))) printm("-");
  670.       if ((type == DATE) && ((x == 4) || (x == 6))) printm("/");
  671. AfterCtrl:
  672.       if ((hot != 0)&&(x >= length)) {
  673.             return (input);
  674.       }
  675.       startt = getxbbstime();
  676.    }
  677.  
  678.   }
  679.   if (chatted) {
  680.     chatted = 0;
  681.     goto AfterChat;
  682.   }
  683.   if ((getxbbstime() - startt) > 240) {
  684.       fputs("\nUser time-out...\n",stdout);
  685.       exit (2);
  686.   }
  687.   return (input);
  688. }
  689.  
  690.  
  691.  
  692. char _fastcall carrchk (void) {  /* Checks for carrier */
  693.  
  694.     union REGS rg;
  695.  
  696.  
  697.     if (baud) {
  698.        rg.x.dx = commport;
  699.        rg.h.ah = GETSTAT;
  700.        int86(20,&rg,&rg);
  701.        if (!(rg.h.al & 128)) {  /* no carrier */
  702.            my_sleep(1);         /* delay a sec, try again */
  703.            rg.x.dx = commport;
  704.            rg.h.ah = GETSTAT;
  705.            int86(20,&rg,&rg);
  706.            if (!(rg.h.al & 128)) {  /* still no carrier, outta here */
  707.                fossil(DTR,DOWN);
  708.                baud=0;
  709.                fputs("\n\04 Lost carrier...\n",stdout);
  710.                exit (1);
  711.            }
  712.        }
  713.        return (rg.h.ah);    /* can be inspected to see if input char is ready */
  714.     }
  715.     return 0;
  716. }
  717.  
  718.  
  719. void _fastcall hitreturn (void) {    /* pause until [Enter] is pressed */
  720.  
  721.     register word x;
  722.  
  723.  
  724.     startt = getxbbstime();
  725.     printm("\r\n[Enter] to continue...");
  726.     while ((getxbbstime() - startt) < 241L) {
  727.         if (inkey() == '\r') goto HeDid;
  728.     }
  729.     fputs("\n\04User time-out...\n",stdout);    /* dump lazy bum */
  730.     exit (2);
  731.  
  732. HeDid:
  733.  
  734.     for(x = 0;x < 22;x++) printm(BACKSPACE);    /* Back over prompt */
  735. }
  736.  
  737.  
  738.  
  739. time_t _fastcall getxbbstime (void) {
  740.  
  741.     /* checks user time, updates mins remaining on status line, warns
  742.        user of impending out-of-time, etc.  returns current time_t */
  743.  
  744.     static time_t xbbs_time,lasttime;
  745.     static int warned = 0,x,y;
  746.  
  747.  
  748.     xbbs_time = time(NULL);
  749.  
  750.     if (timelimit < xbbs_time + 120L && !warned) {
  751.         warned++;
  752.         printfm("\x1b[s\x1b[%d;1H\x1b[K\x1b[0;1;37m",maxy - 2);
  753.         printfm("\07WARNING: %ld mins left!!!\x1b[u",(timelimit - xbbs_time) / 60L);
  754.         fossil(FLUSHOUT,0);
  755.     }
  756.  
  757.     if (timelimit > xbbs_time + 120L && warned) warned = 0;
  758.  
  759.     if (timelimit < xbbs_time) {
  760.         timelimit = xbbs_time + 240L;
  761.         printfm("\x1b[%d;1H\x1b[K\x1b[0;1;37mSorry, time to logoff...",maxy - 2);
  762.         fossil(FLUSHOUT,0);
  763.         exit(0);
  764.     }
  765.  
  766.     if(lasttime != xbbs_time) {
  767.         curr_cursor(&x,&y);
  768.         current_color = 7 * 16;
  769.         dprintf(maxx - 6,maxy,"%-5ld",(timelimit - xbbs_time) / 60L); /* note method of */
  770.         lasttime = time(NULL);                          /* determining time */
  771.         cursor(x,y);                                    /* remaining...     */
  772.     }
  773.  
  774.     return xbbs_time;
  775. }
  776.  
  777.  
  778.  
  779. void _fastcall printinfo (void) { /* Just prints prog info locally */
  780.  
  781.     fprintf(stderr,"  %s\n\04 %s\n\04 Compiled: %s  %s\n",PROGRAM_NAME,COPY_RIGHT,__DATE__,__TIME__);
  782. }
  783.  
  784.  
  785.  
  786. char * _fastcall fidodate (void) {  /* Builds a _correct_ Fido(tm) datestring */
  787.  
  788.     /* this is here because sooooo many people SCREW IT UP */
  789.     /* this is the RIGHT way to make a Fido date string */
  790.     /* see FTS-0001 for more info */
  791.  
  792.  #ifdef __TURBOC__
  793.  
  794.     char months[12][4]={    /* note; newer versions of TC have strftime... */
  795.        "Jan",
  796.        "Feb",
  797.        "Mar",
  798.        "Apr",
  799.        "May",
  800.        "Jun",
  801.        "Jul",
  802.        "Aug",
  803.        "Sep",
  804.        "Oct",
  805.        "Nov",
  806.        "Dec"
  807.     };
  808.     static char fdate[20];
  809.     struct date dos_date;
  810.     struct time dos_time;
  811.  
  812.    /* 26 Jul 89  06:23:47 */
  813.  
  814.     getdate(&dos_date);
  815.     gettime(&dos_time);
  816.  
  817.     sprintf(fdate,"%02hu %s %02d  %02hu:%02hu:%02hu",dos_date.da_day,months[dos_date.da_mon-1],dos_date.da_year%100,dos_time.ti_hour,dos_time.ti_min,dos_time.ti_sec);
  818.                             /*  ^^  */
  819. #else
  820.  
  821.     static char fdate[32];
  822.     time_t t;
  823.  
  824.     t = time(NULL);
  825.     strftime(fdate,31,"%d %a %y  %H:%M:%S",localtime(&t));
  826.                             /* ^^ */
  827. #endif
  828.  
  829.     return(fdate);
  830. }
  831.  
  832.  
  833.  
  834. void _cdecl aprintf (char *string,...) {     /* Local-only messages */
  835.  
  836.     static char buffer[318];
  837.  
  838.  
  839.     va_list ap;
  840.     va_start(ap,string);
  841.     vsprintf(buffer,string,ap);
  842.     va_end(ap);
  843.     ansi((char FAR *)buffer);
  844. }
  845.  
  846.  
  847. void _cdecl debug_print (char *string,...) {     /* Local-only messages */
  848.                                                  /* only displayed if   */
  849.                                                  /* debug_mode is non-0 */
  850.  
  851.     static char buffer[318];
  852.     va_list(ap);
  853.  
  854.  
  855.     if(!debug_mode) return;
  856.     va_start(ap,string);
  857.     vsprintf(buffer,string,ap);
  858.     va_end(ap);
  859.     ansi((char FAR *)buffer);
  860. }
  861.  
  862.  
  863.  
  864. int _cdecl printfm (char *string,...) {  /* Like printf() for local
  865.                                            and remote */
  866.  
  867.     static char buffer[318];
  868.     int val;
  869.     va_list ap;
  870.  
  871.  
  872.     va_start(ap,string);
  873.     val = vsprintf(buffer,string,ap);
  874.     va_end(ap);
  875.     printm(buffer);
  876.     return val;
  877. }
  878.  
  879.  
  880.  
  881. int _fastcall printm (char *text) {   /* Prints local and remote */
  882.  
  883.     int  x;
  884.  
  885.  
  886.     mprint(text);
  887.     x = ansi((char FAR *)text);
  888.     getxbbstime();
  889.     return x;
  890. }
  891.  
  892.  
  893.  
  894. void _fastcall mprint (char *text) {    /* prints remote only */
  895.  
  896.     char *p;
  897.  
  898.  
  899.     if(!baud) return;
  900.     p = text;
  901.     while(*p) {
  902.         while(!fossil(TRANSMIT,*p)) carrchk();
  903.         p++;
  904.     }
  905.     getxbbstime();
  906. }
  907.  
  908.  
  909.  
  910. /* Formatted 'printf-style' output through pd screen writer */
  911.  
  912. int _cdecl dprintf (int x,int y,char *string,...) {
  913.  
  914.     static char buffer[318];
  915.     va_list ap;
  916.  
  917.  
  918.     va_start(ap,string);
  919.     vsprintf(buffer,string,ap);
  920.     va_end(ap);
  921. #ifndef __SCREEN2ASM__
  922.     return(dputs(x,y,buffer));
  923. #else
  924.     return(dputs(x,y,(char FAR *)buffer));
  925. #endif
  926. }
  927.  
  928.  
  929.  
  930. void _fastcall print_stat (void) {     /* Print status line */
  931.  
  932.     current_color = 7 * 16;     /* reverse video */
  933.     dprintf(1,maxy,"%-31.31s \04 %31.31s\04             ",
  934.             PROGRAM_NAME,username);
  935. }
  936.  
  937.  
  938.  
  939. #ifndef __SCREEN2ASM__
  940.  
  941. /*
  942.  * uses this instead of SCREEN2.ASM if all you need direct screen writes for
  943.  * is a status line.  of course, you could extend this to include the other
  944.  * functions in SCREEN2.ASM rewritten in C, but if you need that much, go with
  945.  * the ASM code.
  946.  */
  947.  
  948. int _pascal dputs (int x,int y,char *s) {
  949.  
  950.     register char *p = s;
  951.     int c = (current_color << 8);   /* get calc out of loop */
  952.  
  953.  
  954.     if(!videomethod) {                  /* direct screen writes */
  955.         register int FAR *v;
  956.  
  957.         y--;                            /* dec to 0-based (call as 1-based, */
  958.         x--;                            /* i.e. top left of screen is 1,1)  */
  959.         v = vseg + ((y * maxx) + x++);  /* point v to right spot in vid RAM */
  960.         while(*p) {                     /* until NUL terminator... */
  961.              *v++ = (*p++ | c);         /* display string to vid RAM */
  962.         }
  963.         return (int)p - (int)s;         /* return displayed length */
  964.     }
  965.     else if(videomethod == 1) {         /* bios screen writes */
  966. #ifndef __TURBOC__
  967.         union REGS rg;
  968. #endif
  969.         int        xx,yy;
  970.  
  971.         curr_cursor(&xx,&yy);
  972.         cursor(x,y);
  973.         while(*p) {
  974. #ifndef __TURBOC__
  975.             rg.h.ah = 0x09;             /* write char w/ attrib */
  976.             rg.h.al = *p++;
  977.             rg.h.bh = 0;
  978.             rg.h.bl = (char)c;
  979.             rg.x.cx = 0;
  980.             int86(0x10,&rg,&rg);
  981. #else
  982.             _AH = 0x09;
  983.             _AL = *p++;
  984.             _BH = 0;
  985.             _BL = (char)c;
  986.             _CX = 0;
  987.             geninterrupt(0x10);
  988. #endif
  989.         }
  990.         cursor(xx,yy);
  991.         return strlen(s);
  992.     }
  993.     else {                              /* dos screen writes, no color */
  994.         int        xx,yy;               /* use only as last resort */
  995.  
  996.         curr_cursor(&xx,&yy);
  997.         cursor(x,y);
  998.         c = fprintf(stdout,s);
  999.         cursor(xx,yy);
  1000.         return c;
  1001.     }
  1002. }
  1003.  
  1004. #endif
  1005.